﻿using System;
using System.Text;
using System.Web;
using System.Collections.Generic;

namespace Xushre.WeiBoSDK {
    /// <summary>
    /// OAuth2 授权认证类
    /// </summary>
    public class OAuth2 {

        /// <summary>
        /// 申请应用时分配的AppKey。
        /// </summary>
        public string client_id { get; set; }

        /// <summary>
        /// 申请应用时分配的AppSecret。
        /// </summary>
        public string client_secret { get; set; }

        /// <summary>
        /// 授权回调地址，站外应用需与设置的回调地址一致，站内应用需填写canvas page的地址。
        /// </summary>
        public string redirect_uri { get; set; }

        /// <summary>
        /// 申请scope权限所需参数，可一次申请多个scope权限，用逗号分隔。
        /// </summary>
        public string scope { get; set; }

        /// <summary>
        /// 用于保持请求和回调的状态，在回调时，会在Query Parameter中回传该参数
        /// </summary>
        public string state { get; set; }

        /// <summary>
        /// 授权页面的终端类型，取值见下面的说明。
        /// </summary>
        public string display { get; set; }

        /// <summary>
        /// 是否强制用户重新登录，true：是，false：否。默认false。
        /// </summary>
        public string forcelogin { get; set; }

        /// <summary>
        /// 授权页语言，缺省为中文简体版，en为英文版。
        /// </summary>
        public string language { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string response_type { get; set; }

        /// <summary>
        /// 初始化 OAuth2 类
        /// </summary>
        /// <param name="client_id">申请应用时分配的AppKey。</param>
        /// <param name="client_secret">申请应用时分配的AppSecret。</param>
        /// <param name="redirect_uri">授权回调地址，站外应用需与设置的回调地址一致，站内应用需填写canvas page的地址。</param>
        public OAuth2(string client_id = null, string client_secret = null, string redirect_uri = null) {
            if (client_id != null && client_id != "") {
                this.client_id = client_id;
            }

            if (client_secret != null && client_secret != "") {
                this.client_secret = client_secret;
            }

            if (redirect_uri != null && redirect_uri != "") {
                this.redirect_uri = redirect_uri;
            }
        }

        /// <summary>
        /// 请求用户授权Token
        /// </summary>
        /// <param name="redirect_uri">授权回调地址，站外应用需与设置的回调地址一致，站内应用需填写canvas page的地址。</param>
        /// <param name="response_type"></param>
        /// <returns>JSON 格式的客串</returns>
        public string AuthorizeURL(string redirect_uri = null, string response_type = null) {
            if (!String.IsNullOrEmpty(redirect_uri)) {
                this.redirect_uri = redirect_uri;
            }

            if (!String.IsNullOrEmpty(response_type)) {
                this.response_type = response_type;
            }

            if (String.IsNullOrEmpty(this.response_type)) {
                this.response_type = "code";
            }

            if (String.IsNullOrEmpty(this.redirect_uri)) {
                return "{\"error\":\"Redirect_uri is not set parameters or settings error.\",\"error_code\":9007}";
            }


            if (String.IsNullOrEmpty(client_id)) {
                return "{\"error\":\"Client_id parameter is not set, or sets errors.\",\"error_code\":9008}";
            }

            StringBuilder url = new StringBuilder();
            url.Append(API.OAuth2.AUTHORIZE);
            url.Append("?client_id=" + client_id);
            url.Append("&redirect_uri=" + HttpUtility.UrlEncode(this.redirect_uri));
            url.Append("&response_type=" + this.response_type);

            if (scope != null) {
                url.Append("&scope=" + scope);
            }

            if (state != null) {
                url.Append("&state=" + state);
            }

            if (display != null) {
                url.Append("&display=" + display);
            }

            if (forcelogin == "true" || forcelogin == "false") {
                url.Append("&forcelogin=" + forcelogin);
            }

            if (language != null) {
                url.Append("&language=" + language);
            }

            return url.ToString();
        }

        /// <summary>
        /// 获取授权过的Access Token
        /// </summary>
        /// <param name="type"></param>
        /// <param name="data"></param>
        /// <returns>JSON 格式的客串</returns>
        /// <exception cref="WeiboException"></exception>
        public string AccessToken(Dictionary<string, string> data = null, string type = "code") {
            string client_id = null;
            string client_secret = null;
            string grant_type = null;

            Dictionary<string, object> postData = new Dictionary<string, object>();

            if (data.TryGetValue("client_id", out client_id)) {
                postData.Add("client_id", client_id);
            } else if (this.client_id != null) {
                postData.Add("client_id", this.client_id);
            } else {
                return "{\"error\":\"client_id parameter is not set, or sets errors!\",\"error_code\":9001}";
            }

            if (data.TryGetValue("client_secret", out client_secret)) {
                postData.Add("client_secret", client_secret);
            } else if (this.client_secret != null) {
                postData.Add("client_secret", this.client_secret);
            } else {
                return "{\"error\":\"client_secret parameter is not set, or sets errors!\",\"error_code\":9002}";
            }

            if (!data.TryGetValue("grant_type", out grant_type)) {
                grant_type = "authorization_code";
            }

            postData.Add("grant_type", grant_type);

            switch (grant_type.ToLower()) {
                case "authorization_code":
                    string code = null;
                    string redirect_uri = null;
                    if (!data.TryGetValue("code", out code)) {
                        return "{\"error\":\"Parameter code is not set or sets errors.\",\"error_code\":9009}";
                    }

                    if (!data.TryGetValue("redirect_uri", out redirect_uri)) {
                        redirect_uri = this.redirect_uri;
                    }

                    if (String.IsNullOrEmpty(redirect_uri)) {
                        return "{\"error\":\"Redirect_uri is not set parameters or settings error.\",\"error_code\":9007}";
                    }

                    postData.Add("code", code);
                    postData.Add("redirect_uri", redirect_uri);
                    break;
                case "password":
                    break;
                case "refresh_token":
                    break;
                default:
                    return "{\"error\":\"wrong auth type.\",\"error_code\":9010}";
            }

            string response = string.Empty;

            try {
                byte[] temp = Tools.Post(API.OAuth2.ACCESS_TOKEN, postData);

                response = Encoding.UTF8.GetString(temp);
            } catch (WeiboException e) {
                throw e;
            }

            return response;
        }


        /// <summary>
        /// 授权信息查询接口
        /// </summary>
        /// <param name="access_token">用户授权时生成的access_token。</param>
        /// <returns>JSON 格式的客串</returns>
        /// <exception cref="WeiboException"></exception>
        public string GetTokenInfo(string access_token) {
            if (String.IsNullOrEmpty(access_token)) {
                return "{\"error\":\"Failed to set parameters access_token or sets errors.\",\"error_code\":9011}";
            }

            string data = "access_token=" + access_token;

            string tokenInfo = string.Empty;

            try {
                byte[] temp = Tools.Post(API.OAuth2.GET_TOKEN_INFO, data);
                tokenInfo = Encoding.UTF8.GetString(temp);
            } catch (WeiboException e) {
                throw e;
            }
            
            return tokenInfo;
        }
    }
}
